import TransWorker from './transcode.worker.js?worker';

class TTSRecorder {
  constructor({
    text = '',
    transWorker,
    wsUrl = 'ws://192.168.5.200:8082/qiwei/tts/websocket',
  } = {}) {
    this.text = text;
    this.audioData = [];
    this.rawAudioData = [];
    this.audioDataOffset = 0;
    this.wsUrl = wsUrl;
    this.audioStarted = false;
    this.status = "init"; // init connecting endPlay

    this.transWorker = transWorker || new TransWorker();
    this.transWorker.onmessage = (e) => {
      this.audioData = this.audioData.concat(e.data.data);
      this.rawAudioData = this.rawAudioData.concat(e.data.rawAudioData);
      if (!this.audioStarted) {
        this.audioStarted = true;
        this.audioPlay();
      }
    };
  }

  /**
   * 内部方法：更新状态
   */
  setStatus(status,msg=null) {
    this.getPlaybackState && this.getPlaybackState(this.status,status,msg)
    this.status = status;
  }

  /**
   * 设置文本参数
   */
  setParams({ text }) {
    if (typeof text === 'string') {
      this.text = text;
    }
  }

  /**
   * 清空缓存音频数据
   */
  clearAudioData({ full = false } = {}) {
    this.audioData = [];
    this.rawAudioData = [];
    this.audioDataOffset = 0;
    this.audioStarted = false;
    this.setStatus("init");

    if (full && this.audioContext) {
      this.audioContext.close().catch(console.warn);
      this.audioContext = null;
    }
  }

  /**
   * 初始化音频播放环境
   */
  audioInit() {
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (!AudioContext) {
      this.setStatus("error");
      throw new Error('该浏览器不支持 Web Audio API');
    }

    if (!this.audioContext) {
      this.audioContext = new AudioContext();
    }
    this.audioContext.resume();
  }

  /**
   * 播放音频数据
   */
  audioPlay() {
    this.setStatus("play");
    if (!this.audioContext) {
      this.audioInit();
    }

    const remaining = this.audioData.length - this.audioDataOffset;

    if (remaining <= 0) {
      setTimeout(() => {
        if (this.audioData.length > this.audioDataOffset) {
          this.audioPlay();
        } else {
          this.setStatus("endPlay");
          this.clearAudioData();
        }
      }, 300);
      return;
    }

    this.setStatus("play");

    const segment = this.audioData.slice(this.audioDataOffset);
    const buffer = this.audioContext.createBuffer(1, segment.length, 22050);
    buffer.copyToChannel(new Float32Array(segment), 0, 0);

    const source = this.audioContext.createBufferSource();
    source.buffer = buffer;
    source.connect(this.audioContext.destination);
    source.start();

    this.audioDataOffset += segment.length;
    this.bufferSource = source;

    source.onended = () => {
      if (this.audioDataOffset < this.audioData.length) {
        this.audioPlay();
      } else {
        setTimeout(() => {
          if (this.audioDataOffset < this.audioData.length) {
            this.audioPlay();
          } else {
            this.setStatus("endPlay");
            this.clearAudioData();
          }
        }, 300);
      }
    };
  }

  /**
   * 建立 WebSocket 连接
   */
  connectWebSocket() {
    this.setStatus("ttsing");
    return new Promise((resolve, reject) => {
      if (!window.WebSocket) { 
        return reject(new Error('浏览器不支持 WebSocket'));
      }      
      const ws = new WebSocket(this.wsUrl);
      this.ttsWS = ws;

      ws.onopen = () => {
        const payload = {
          text: this.text
        };
        ws.send(JSON.stringify(payload));
        resolve();
      };

      ws.onmessage = (e) => {
        try {          
          if( !["ping"].includes(e.data)){
              const data = JSON.parse(e.data);
              if(data.c === "100"){
                  if(data.d === 'finished'){
                    this.ttsWS.close();
                  }else{
                    this.transWorker.postMessage(data.d);
                  }                  
                }else {
                  this.ttsWS.close();
                  this.setStatus("errorTTS");
                  if(data.c === "3010"){
                    this.setStatus("error",data.m);
                  }else {
                    this.setStatus("error");
                  }
              }
          }else {
            this.ttsWS.send("ping");
          }
        } catch (err) {
          this.setStatus("errorTTS");
          console.error('解析 WebSocket 消息失败:', err);
        }
      };

      ws.onerror = (e) => {
        console.error('WebSocket 错误:', e);
        this.setStatus("errorTTS");
        reject(e);
      };

      ws.onclose = () => {
        console.log('WebSocket 连接关闭');
      };
    });
  }

  /**
   * 启动合成流程
   */
  start() {
    this.clearAudioData();
    try {
      this.audioInit();
      this.connectWebSocket().catch((e) => {
        console.error('连接语音合成服务失败:', e);
        this.setStatus("error");
      });
    } catch (e) {
      this.setStatus("error");
      throw e;
    }
  }

  /**
   * 停止播放
   */
  stop() {
    if (this.bufferSource) {
      try {
        this.bufferSource.stop();
      } catch (e) {
        this.setStatus("endPlay");
        console.warn('停止播放失败:', e);
      }
    }

    if (this.ttsWS && this.ttsWS.readyState === WebSocket.OPEN) {
      this.ttsWS.close();
    }

    this.setStatus("endPlay");
    this.clearAudioData({ full: true });
  }
}

export default TTSRecorder;